<template>
  <div class="reviews-container">
    <!-- 评价统计与发布入口 -->
    <div class="reviews-stats" v-if="topLevelReviews.length > 0 || avgScore >= 0">
      <div class="rating-overview">
        <div class="rating-score">
          <span class="score">{{ displayAvgScore }}</span>
          <span class="score-label">综合评分</span>
        </div>
        <div class="rating-details">
          <div class="rating-item" v-for="rating in ratingDistribution" :key="rating.star">
            <span class="rating-label">{{ rating.star }} 星</span>
            <div class="rating-bar">
              <div 
                class="rating-progress" 
                :style="{ width: rating.percentage + '%' }"
              ></div>
            </div>
            <span class="rating-count">{{ rating.count }}</span>
          </div>
        </div>
      </div>

      <!-- 评价筛选 -->
      <div class="reviews-filter">
        <button 
          class="filter-btn" 
          :class="{ active: currentFilter === 'all' }"
          @click="setFilter('all')"
        >
          全部评价
        </button>
        <button 
          class="write-review-btn" 
          @click="openDialog"
        >
          写评论
        </button>
      </div>
    </div>

    <!-- 评价列表 -->
    <div class="reviews-list">
      <div class="review-thread" v-for="review in filteredTopLevel" :key="review.id">
        <ReviewCard 
          :review="mapToCard(review)"
          :current-user-id="Number(userStore.userId) || undefined"
          :reply-count="childReplyTotal[review.id] || (review.children?.length || 0)"
          :is-liked="likeStatusMap[review.id] || false"
          @reply="() => onReply(review)"
          @like="(card: any) => onLike(card)"
          @delete="(card: any) => onDelete(card)"
        />
        <div class="children-list" v-if="review.children && review.children.length">
          <ReviewCard 
            v-for="child in review.children" 
            :key="child.id" 
            :review="mapToCard(child)"
            :current-user-id="Number(userStore.userId) || undefined"
            :compact="true"
            :reply-count="0"
            :is-liked="likeStatusMap[child.id] || false"
            @reply="() => onReply(child)"
            @like="(card: any) => onLike(card)"
            @delete="(card: any) => onDelete(card)"
          />
          <div 
            class="more-replies-text"
            v-if="review.hasMoreChildren"
            @click="loadMoreReplies(review)"
            :class="{ 'loading': replyLoading[review.id] }"
          >
            查看更多回复 ↓
          </div>
        </div>
      </div>
    </div>

    <!-- 没有评价时显示 -->
    <div class="no-reviews" v-if="topLevelReviews.length === 0">
      <div class="no-reviews-content">
        <div class="no-reviews-icon">
          <el-icon><Star /></el-icon>
        </div>
        <div class="no-reviews-text">暂无评价</div>
    </div>
    </div>

    <!-- 发布评价对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="520px">
      <div class="dialog-body">
        <div class="star-picker" v-if="!isReplyMode">
          <span 
            v-for="n in 5" 
            :key="n" 
            class="star" 
            :class="{ active: n <= newReview.score }" 
            @click="newReview.score = n"
          >★</span>
          <span class="star-hint">{{ newReview.score }} 分</span>
        </div>
        <el-input
          v-model="newReview.content"
          type="textarea"
          :rows="5"
          placeholder="说说你的使用感受吧"
          maxlength="300"
          show-word-limit
        />
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" :loading="submitting" @click="submitReview">提交</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
  
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { Star } from '@element-plus/icons-vue'
import ReviewCard from './ReviewCard.vue'
import { useUserStore } from '../../stores/user'
import { ElMessage } from 'element-plus'
import { createReview, replyReview, getTopWithPreview, countTopReviews, getScoreStats, likeReview, getLikeStatus, deleteReview, getReplies, type ReviewNode } from '../../api/review'

const props = withDefaults(defineProps<{
  productId: number
  avgScore?: number
}>(), {
  avgScore: 0,
  commentCount: 0
})

const emit = defineEmits<{
  reviewSubmitted: []
  reviewDeleted: []
  countUpdated: [count: number]
}>()

const userStore = useUserStore()
const currentFilter = ref<'all'>('all')
const dialogVisible = ref(false)
const submitting = ref(false)
const isReplyMode = ref(false)
const replyContext = ref<{ parentId: string; replyUserId?: number; replyUserName?: string } | null>(null)
const page = ref(1)
const size = ref(10)
const totalCount = ref(0)
const topLevelReviews = ref<ReviewNode[]>([])
const scoreStats = ref<Record<number, number> | null>(null)
const childReplyTotal = ref<Record<string, number>>({})
const childReplyPage = ref<Record<string, number>>({})
const childReplySize = 10
const replyLoading = ref<Record<string, boolean>>({})
// 存储评论的点赞状态
const likeStatusMap = ref<Record<string, boolean>>({})

const newReview = ref({
  score: 5,
  content: ''
})

const dialogTitle = computed(() => (isReplyMode.value ? '回复评论' : '发表评价'))

const displayAvgScore = computed(() => {
  if (typeof props.avgScore === 'number') return props.avgScore.toFixed(1)
  // 后备：用当前已加载评论估算
  if (topLevelReviews.value.length === 0) return '0.0'
  const sum = topLevelReviews.value.reduce((s, r) => s + (r.score || 0), 0)
  return (sum / topLevelReviews.value.length).toFixed(1)
})

const ratingDistribution = computed(() => {
  const counts = scoreStats.value
  if (counts) {
    const total = (counts[1] || 0) + (counts[2] || 0) + (counts[3] || 0) + (counts[4] || 0) + (counts[5] || 0)
    return [5,4,3,2,1].map(star => ({
      star,
      count: counts[star] || 0,
      percentage: total ? (counts[star] || 0) / total * 100 : 0
    }))
  }
  // fallback to computed from loaded reviews
  const total = topLevelReviews.value.length
  const countBy: Record<number, number> = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 }
  topLevelReviews.value.forEach(r => {
    const s = Math.min(5, Math.max(1, r.score || 0))
    if (s >= 1) countBy[s] = (countBy[s] || 0) + 1
  })
  return [5,4,3,2,1].map(star => ({
    star,
    count: countBy[star] || 0,
    percentage: total ? (countBy[star] || 0) / total * 100 : 0
  }))
})

const filteredTopLevel = computed(() => topLevelReviews.value)

function mapToCard(r: ReviewNode) {
  return {
    id: r.id,
    userName: r.userName || `用户${String(r.userId).slice(-4)}`, // 优先使用API返回的userName
    userAvatar: r.userPic || 'https://api.dicebear.com/7.x/personas/svg?seed=user',
    date: r.createTime,
    content: r.content,
    likeCount: r.likeCount || 0,
    userId: r.userId
  }
}

async function loadCount() {
  const res = await countTopReviews(props.productId)
  // 大多数 request 封装直接返回 data
  totalCount.value = Number(res.data ?? res?.data?.data ?? 0)
  console.log('Reviews组件获取到评论总数:', totalCount.value)
  // 向父组件发送评论总数更新
  emit('countUpdated', totalCount.value)
}

async function loadTopLevel() {
  const res = await getTopWithPreview(props.productId, page.value, size.value)
  // 兼容两种返回：直接数组 或 Result.data
  const list = (Array.isArray(res.data) ? res.data : (res.data?.data || [])) as ReviewNode[]
  topLevelReviews.value = list
  
  // 如果用户已登录，加载所有评论的点赞状态
  if (userStore.isLoggedIn && userStore.userId) {
    await loadLikeStatusForReviews(list)
  }
}

// 加载评论的点赞状态
async function loadLikeStatusForReviews(reviews: ReviewNode[]) {
  if (!userStore.isLoggedIn || !userStore.userId) return
  
  const userId = Number(userStore.userId)
  const allReviews: ReviewNode[] = []
  
  // 收集所有顶层评论和子评论
  reviews.forEach(review => {
    allReviews.push(review)
    if (review.children) {
      allReviews.push(...review.children)
    }
  })
  
  // 并发查询点赞状态
    await Promise.all(allReviews.map(async (review) => {
      try {
        const res = await getLikeStatus(review.id, userId)
        // 解析接口返回的点赞状态 - response.data包含code、message、data
        likeStatusMap.value[review.id] = res?.data || false
      } catch (error) {
        console.error(`获取评论 ${review.id} 点赞状态失败:`, error)
        likeStatusMap.value[review.id] = false
      }
    }))
}

async function loadScoreStats() {
  const res = await getScoreStats(props.productId)
  const data = res.data || res?.data?.data || {}
  // 后端 key 可能为字符串 '1'...'5'
  const normalized: Record<number, number> = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 }
  for (const k of Object.keys(data)) {
    const keyNum = Number(k)
    if (keyNum >= 1 && keyNum <= 5) {
      normalized[keyNum] = Number(data[k]) || 0
    }
  }
  scoreStats.value = normalized
}

function openReplyDialog(target: ReviewNode) {
  if (!userStore.isLoggedIn) {
    ElMessage.warning('请先登录再进行回复')
    return
  }
  isReplyMode.value = true
  newReview.value.content = ''
  replyContext.value = {
    parentId: target.level === 1 ? target.id : (target.parentId || ''),
    replyUserId: target.userId,
    replyUserName: target.userName  // 保存被回复人的用户名
  }
  dialogVisible.value = true
}

// 打开写评论对话框
function openDialog() {
  if (!userStore.isLoggedIn) {
    ElMessage.warning('请先登录再发表评价')
    return
  }
  isReplyMode.value = false
  newReview.value = {
    score: 5,
    content: ''
  }
  replyContext.value = null
  dialogVisible.value = true
}

async function submitReview() {
  if (!props.productId) return
  if (!newReview.value.content.trim()) {
    ElMessage.warning('请输入评价内容')
    return
  }
  submitting.value = true
  try {
    if (isReplyMode.value && replyContext.value) {
      // 子评论（回复）- 只刷新评价组件内部
      await replyReview({
        parentId: replyContext.value.parentId,
        itemId: props.productId,
        userId: Number(userStore.userId) || 0,
        userName: userStore.username || undefined,
        userPic: userStore.avatar || undefined,
        replyUserId: replyContext.value.replyUserId,
        replyUserName: replyContext.value.replyUserName,
        content: newReview.value.content
      })
      ElMessage.success('回复已提交')
      // 子评论只刷新组件内部数据，不刷新整个页面
      // 只刷新评价相关的接口，保持页面位置不变
      await Promise.all([
        loadCount(),       // 刷新评价总数 http://localhost:5173/api/reviews/item/1/count
        loadScoreStats()   // 刷新评分统计 http://localhost:5173/api/reviews/item/1/score-stats
      ])
      // 只刷新对应的父评论的子评论数据，保持当前展开状态
      const parentReview = topLevelReviews.value.find(r => r.id === replyContext.value?.parentId)
      if (parentReview) {
        // 重置该父评论的分页状态，重新加载第一页子评论
        childReplyPage.value[parentReview.id] = 1
        parentReview.children = []
        await loadMoreReplies(parentReview)
      }
      

    } else {
      // 主评价 - 需要刷新整个页面
      await createReview({
        itemId: props.productId,
        userId: Number(userStore.userId) || 0,
        userName: userStore.username || undefined,
        userPic: userStore.avatar || undefined,
        content: newReview.value.content,
        score: newReview.value.score
      })
      ElMessage.success('评价提交成功')
      // 主评价提交后通知父组件刷新整个页面
      emit('reviewSubmitted')
    }
    dialogVisible.value = false
  } catch (e) {
    ElMessage.error('提交失败，请稍后重试')
  } finally {
    submitting.value = false
  }
}

function setFilter(f: 'all') {
  currentFilter.value = f
}

onMounted(async () => {
  await reloadAllData()
})

// 重新加载所有评价数据（用于父组件调用）
async function reloadAllData() {
  await Promise.all([loadTopLevel(), loadCount(), loadScoreStats()])
}



// 暴露给父组件的方法
defineExpose({
  reloadAllData
})

async function onLike(card: { id: string; increment: number }) {
  try {
    if (!userStore.isLoggedIn || !userStore.userId) {
      ElMessage.warning('请先登录')
      return
    }
    
    const userId = Number(userStore.userId)
    const { id, increment } = card
    
    // 1. 乐观更新：立即更新本地状态，无需等待后端返回
    // 保存原始状态，用于可能的回滚
    // 更新点赞状态
    likeStatusMap.value[id] = increment === 1
    
    // 更新点赞数量
    const review = findReviewById(id)
    if (review) {
      review.likeCount = (review.likeCount || 0) + increment
    }
    
    // 2. 异步调用点赞接口
    await likeReview(id, increment, userId)
    
    // 3. 接口调用成功后，可以选择重新查询点赞状态确保完全同步
    // 但由于是乐观更新，这里可以省略
  } catch (e) {
    // 4. 接口调用失败，回滚乐观更新
    const { id, increment } = card
    likeStatusMap.value[id] = increment === 1 ? false : true
    
    const review = findReviewById(id)
    if (review) {
      review.likeCount = (review.likeCount || 0) - increment
    }
    
    console.error('点赞操作失败:', e)
    
    // 5. 重新查询点赞状态，确保最终与后端一致
    if (userStore.isLoggedIn && userStore.userId) {
      try {
        const userId = Number(userStore.userId)
        const res = await getLikeStatus(id, userId)
        likeStatusMap.value[id] = res?.data || false
        
        // 再次修正点赞数量
        await loadTopLevel()
      } catch (innerError) {
        console.error('重新同步点赞状态失败:', innerError)
      }
    }
  }
}

function onReply(target: ReviewNode) {
  openReplyDialog(target)
}

async function onDelete(card: any) {
  try {
    await deleteReview(card.id)
    ElMessage.success('已删除')
    // 删除评价后通知父组件刷新整个页面
    emit('reviewDeleted')
  } catch (e) {
    ElMessage.error('删除失败')
  }
}

async function loadMoreReplies(review: ReviewNode) {
  const parentId = review.id
  // 设置loading状态
  replyLoading.value[parentId] = true
  
  try {
    const currentPage = childReplyPage.value[parentId] || 1
    const res = await getReplies(parentId, currentPage, childReplySize)
    // 兼容两种返回：直接数组 或 Result.data
    const list = (Array.isArray(res.data) ? res.data : (res.data?.data || [])) as ReviewNode[]
    // 追加到 children 末尾，但要避免重复
    if (!review.children) review.children = []
    
    // 获取已存在的评论ID集合，用于去重
    const existingIds = new Set(review.children.map(child => child.id))
    // 过滤出新评论（不在现有评论中的）
    const newReplies = list.filter(reply => !existingIds.has(reply.id))
    // 只添加新的评论
    review.children.push(...newReplies)
    
    // 如果返回数量等于 pageSize，说明可能还有下一页
    if (list.length === childReplySize) {
      childReplyPage.value[parentId] = currentPage + 1
    } else {
      // 如果返回数量小于 pageSize，说明没有更多数据了
      review.hasMoreChildren = false
    }
  } catch (error) {
    ElMessage.error('加载更多回复失败，请稍后重试')
  } finally {
    // 重置loading状态
    replyLoading.value[parentId] = false
  }
}

// 辅助函数：通过ID查找评论
function findReviewById(id: string): ReviewNode | undefined {
  // 先在顶层评论中查找
  let found = topLevelReviews.value.find(review => review.id === id)
  if (found) return found
  
  // 如果顶层评论中没找到，再在所有子评论中查找
  for (const review of topLevelReviews.value) {
    if (review.children) {
      found = review.children.find(child => child.id === id)
      if (found) return found
    }
  }
  
  return undefined
}
</script>

<style scoped lang="scss">
.reviews-container {
  background: #fff;
  border-radius: 0.5rem;
  padding: 1.5rem;
  margin-top: 1rem;

  .reviews-stats {
    margin-bottom: 1.5rem;

    .rating-overview {
      display: flex;
      margin-bottom: 1.5rem;

      .rating-score {
        display: flex;
        flex-direction: column;
        align-items: center;
        margin-right: 2rem;
        padding-right: 2rem;
        border-right: 1px solid #eee;

        .score {
          font-size: 2rem;
          font-weight: bold;
          color: #ff6b6b;
        }

        .score-label {
          color: #999;
          font-size: 0.875rem;
          margin-top: 0.25rem;
        }
      }

      .rating-details {
        flex: 1;

        .rating-item {
          display: flex;
          align-items: center;
          margin-bottom: 0.5rem;

          .rating-label {
            width: 4rem;
            color: #666;
            font-size: 0.875rem;
          }

          .rating-bar {
            flex: 1;
            height: 0.5rem;
            background: #f0f0f0;
            border-radius: 0.25rem;
            overflow: hidden;
            margin: 0 1rem;

            .rating-progress {
              height: 100%;
              background: #ff6b6b;
              transition: width 0.3s ease;
            }
          }

          .rating-count {
            color: #999;
            font-size: 0.75rem;
          }
        }
      }

      .publish-box {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        gap: 0.5rem;

        .publish-btn {
          background: #ee5530;
          color: #fff;
          border: none;
          padding: 0.5rem 1rem;
          border-radius: 0.25rem;
          cursor: pointer;
        }

        .count-text {
          color: #999;
          font-size: 0.75rem;
        }
      }
    }

    .reviews-filter {

.filter-btn {
background: none;
border: none;
padding: 0.5rem 1rem;
margin-right: 1.5rem;
color: #666;
cursor: pointer;
font-size: 0.875rem;
position: relative;

&.active {
color: #ff6b6b;

&::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 2px;
background: #ff6b6b;
}
}

&:hover:not(.active) {
color: #ff6b6b;
}
}

.write-review-btn {
background: #ff6b6b;
border: none;
padding: 0.5rem 1.5rem;
color: white;
cursor: pointer;
font-size: 0.875rem;
border-radius: 4px;
transition: all 0.3s;
        border-radius: 999px;
        padding: 0.25rem 0.5rem;
        margin-right: 1rem;
        font-size: 0.75rem;
      }

      .publish-inline {
        background: linear-gradient(135deg, #ff8a5c, #ee5530);
        color: #fff;
        border: none;
        padding: 0.4rem 0.9rem;
        border-radius: 0.375rem;
        cursor: pointer;
        box-shadow: 0 2px 8px rgba(238,85,48,0.3);
      }
    }
  }

  .reviews-list {
    .review-thread {
      margin-bottom: 0.5rem;
    }
    .children-list {
      margin-left: 2rem;
      border-left: 2px solid #f0f0f0;
      padding-left: 1rem;
      padding-top: 0.125rem;
      padding-bottom: 0.125rem;
      margin-top: 0.25rem;
      .review-card {
        background: #fcfcfc;
      }
    }
    .more-replies-text {
      display: inline-block;
      color: #999;
      font-size: 0.75rem;
      cursor: pointer;
      padding: 0.25rem 0;
      margin-top: 0.25rem;
      margin-left: 2rem;
      border-top: 1px solid #f0f0f0;
      transition: color 0.2s ease;
      
      &:hover:not(.loading) {
        color: #666;
      }
      
      &.loading {
        opacity: 0.6;
        cursor: not-allowed;
      }
    }
    
    /* 防止加载更多时页面抖动的占位样式 */
    .replies-placeholder {
      min-height: 2rem;
    }
  }

  .no-reviews {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 4rem 0;

    .no-reviews-content {
      text-align: center;

      .no-reviews-icon {
        font-size: 3rem;
        color: #eee;
        margin-bottom: 1rem;
      }

      .no-reviews-text {
        color: #999;
        font-size: 0.875rem;
      }
    }
  }
}

.dialog-body {
  .star-picker {
    margin-bottom: 1rem;
    .star {
      font-size: 1.5rem;
      color: #ddd;
      cursor: pointer;
      margin-right: 0.25rem;
      &.active {
        color: #ffb400;
      }
    }
    .star-hint {
      margin-left: 0.5rem;
      color: #666;
      font-size: 0.875rem;
    }
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .reviews-container {
    padding: 1rem;
  }

  .rating-overview {
    flex-direction: column;

    .rating-score {
      margin-right: 0;
      padding-right: 0;
      border-right: none;
      margin-bottom: 1rem;
    }
  }

  .reviews-filter {
    flex-wrap: wrap;

    .filter-btn {
      margin-bottom: 0.5rem;
    }
  }
}
</style>